package com.coldtech.circlecrash.handler;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import com.coldtech.circlecrash.Screen;
import com.coldtech.circlecrash.SquareField;
import com.coldtech.circlecrash.units.Unit;

public class UnitHandler {
	private Screen screen = null;
	private SquareField squareField = null;
	private List<Unit> unitList = null;

	public UnitHandler(Screen screen, SquareField squareField) {
		this.screen = screen;
		this.squareField = squareField;
		this.unitList = new ArrayList<Unit>();
	}

	public SquareField getSquareField() {
		return this.squareField;
	}

	public void addUnit(Unit unit) {
		this.squareField.addUnit(unit);
		this.unitList.add(unit);
		checkCollision(unit);
	}

	public void removeUnit(Unit unit) {
		int ui = this.unitList.indexOf(unit);
		if (ui != -1) {
			unit.getSquare().removeUnit(unit);
			this.unitList.remove(ui);
		}
	}

	public void tick() {
		for (int i = 0; i < this.unitList.size(); i++) {
			this.unitList.get(i).update();
			move(this.unitList.get(i));
		}
	}

	public void update() {
		for (int i = 0; i < unitList.size(); i++) {
			this.unitList.get(i).update();
		}
	}

	public void draw() {
		for (int i = 0; i < this.unitList.size(); i++) {
			this.screen.drawUnit(this.unitList.get(i));
		}
	}

	private void move(Unit unit) {
		unit.move();
		// if (unit.isMoving()) {
		checkCollision(unit);
		// }
	}

	private void checkCollision(Unit unit) {
		if (unit.getSquare() != null) {
			Unit unit2 = null;
			List<Unit> units = unit.getSquare().getSquareBlock().getUnits();

			for (int i = 0; i < units.size(); i++) {
				unit2 = units.get(i);
				if (unit2 != null) {
					if (unit != unit2) {
						if (unit.getPlayer() != unit2.getPlayer()) {
							moveUnitsTogether(unit, unit2);
						} else {
							if (isCollision(unit.getPosition(),
									unit.getRadius(), unit2.getPosition(),
									unit2.getRadius())) {
								moveUnitsAway(unit, unit2);
							}
						}
					}
				}
			}
		}
	}

	private void moveUnitsAway(Unit unit1, Unit unit2) {
		final double ddiv = getDistance(unit1, unit2);

		final double vxdif = (unit2.getVelocity().getX() - unit1.getVelocity()
				.getX()) / 2;
		final double vydif = (unit2.getVelocity().getX() - unit1.getVelocity()
				.getX()) / 2;

		final double velX = ((unit2.getPosition().getX() - unit1.getPosition()
				.getX()) / 100);
		final double velY = ((unit2.getPosition().getY() - unit1.getPosition()
				.getY()) / 100);

		final double posX = (unit2.getPosition().getX() - unit1.getPosition()
				.getX()) / 100;
		final double posY = (unit2.getPosition().getY() - unit1.getPosition()
				.getY()) / 100;

		if (!unit1.isMother()) {
			/*
			 * if (!Double.isNaN(posx) && !Double.isNaN(posy)) {
			 * unit1.addPos(-(posx * unit2.getRadius()), -(posy *
			 * unit2.getRadius())); }
			 */
			unit1.addVelocity(-velX, -velY);
		}
		if (!unit2.isMother()) {
			/*
			 * if (!Double.isNaN(posx) && !Double.isNaN(posy)) {
			 * unit2.addPos((posx * unit1.getRadius()), (posy *
			 * unit1.getRadius())); }
			 */
			unit2.addVelocity(velX, velY);
		}
	}

	private void moveUnitsTogether(Unit unit1, Unit unit2) {
		final double ddiv = getDistance(unit1, unit2);

		final double vxdif = (unit2.getVelocity().getX() - unit1.getVelocity()
				.getX()) / 2;
		final double vydif = (unit2.getVelocity().getX() - unit1.getVelocity()
				.getX()) / 2;

		final double velX = ((unit2.getPosition().getX() - unit1.getPosition()
				.getX()) / 100);
		final double velY = ((unit2.getPosition().getY() - unit1.getPosition()
				.getY()) / 100);

		final double posX = (unit2.getPosition().getX() - unit1.getPosition()
				.getX()) / 100;
		final double posY = (unit2.getPosition().getY() - unit1.getPosition()
				.getY()) / 100;

		if (isCollision(unit1.getPosition(), unit1.getRadius(),
				unit2.getPosition(), unit2.getRadius())) {
			if (!unit1.isMother()) {
				if (!unit1.isMother()) {
					unit1.addVelocity(-velX * 20, -velY * 20);
				}
				unit1.setSize(unit1.getSize() - 2);
				if (unit1.getSize() == unit1.MIN_SIZE) {
					removeUnit(unit1);
				}
				if (!unit2.isMother()) {
					unit2.addVelocity(velX * 20, velY * 20);
				}
				unit2.setSize(unit2.getSize() - 2);
				if (unit2.getSize() == unit1.MIN_SIZE) {
					removeUnit(unit2);
				}
			}
			if (!unit2.isMother()) {
				if (!unit1.isMother()) {
					unit1.addVelocity(-velX * 20, -velY * 20);
				}
				unit1.setSize(unit1.getSize() - 2);
				if (unit1.getSize() == unit1.MIN_SIZE) {
					removeUnit(unit1);
				}
				if (!unit2.isMother()) {
					unit2.addVelocity(velX * 20, velY * 20);
				}
				unit2.setSize(unit2.getSize() - 2);
				if (unit2.getSize() == unit1.MIN_SIZE) {
					removeUnit(unit2);
				}
			}
		} else {
			if (!unit1.isMother()) {
				unit1.addVelocity(velX, velY);
			}
			if (!unit2.isMother()) {
				unit2.addVelocity(-velX, -velY);
			}
		}
	}

	private boolean isCollision(Point2D.Double p1, double r1,
			Point2D.Double p2, double r2) {
		final double a = r1 + r2;
		final double dx = p1.x - p2.x;
		final double dy = p1.y - p2.y;
		return a * a > (dx * dx + dy * dy);
	}

	private float getDistance(Unit unit1, Unit unit2) {
		return (float) unit1.getPosition().distanceSq(unit2.getPosition());
	}

	private float getVelocityDiff(Unit unit1, Unit unit2) {
		return (float) unit1.getVelocity().distanceSq(unit2.getVelocity());
	}
}
